namespace BM.Tools.WebControls.MForm.Controls
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Web.UI;
    using System.Xml.XPath;

    using BM.Tools.WebControls.MForm.Controls.Items;

    using Helper;

    /// <summary>
    /// Choice is an <see cref="Offspring" /> control that corresponds to a set of xml chunks of which only one chunk can appear in the xml tree
    /// </summary>
    [ToolboxData(@"<{0}:Choice runat=""server"" ></{0}:Branch>")]
    public class Choice : OffspringsOwner
    {
        /// <summary>
        /// Gets a value indicating whether the control is optional. 
        /// It is optional when it can appear either never or at most once.
        /// </summary>       
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual bool IsOptional
        {
            get
            {
                return MinOccurs == 0 && MaxOccurs == 1;
            }
        }

        /// <summary>
        /// Gets XPathString.
        /// </summary>
        /// <value>
        /// The x path string.
        /// </value>
        internal override string XPathString
        {
            get
            {
                var dummyItem = new ChoiceItem(this, 0);
                return String.Join(" | ", dummyItem.Offsprings.Select(offspring => offspring.XPathName).ToArray());
            }
        }

        /// <summary>
        /// Gets a value indicating whether the parent passed multiple nodes to children
        /// </summary>
        internal bool PassMultipleNodesToChildren
        {
            get
            {
                return MaxOccurs == 1;
            }
        }

        /// <summary>
        /// Gets information how many items should be rendered at least by default.
        /// This value will be used if the <see cref="Offspring.MinRenderedOccurs" /> was not set.
        /// By default in case of a <see cref="Choice"/>, the item is rendered once if it is optional.
        /// </summary>       
        protected override int DefaultMinRenderedOccurs
        {
            get
            {
                return MaxOccurs == 1 ? 1 : base.DefaultMinRenderedOccurs;
            }
        }

        /// <summary>
        /// returns a node iterator over nodes from the data source that match the offspring name.
        /// Decides if multiple nodes should create multiple choice controls or multiple child controls.
        /// </summary>
        protected override IEnumerable<IXPathNavigable> Navigables
        {
            get
            {
                if (PassMultipleNodesToChildren)
                {
                    return MultipleChildrenNavigables;
                }

                return base.Navigables;                            
            }            
        }

        private IEnumerable<IXPathNavigable> MultipleChildrenNavigables
        {
            get
            {
                var dataSource = this.GetDataSource();

                if (dataSource == null)
                {
                    return null;
                }

                var navigableDataSource = dataSource as IXPathNavigable ?? dataSource.ToXPathDocument();

                var navigator = navigableDataSource.CreateNavigator();
                if (navigator.Select(XPathString, Manager).Count > 0)
                {
                    return navigator.Select("self::*", Manager).Cast<IXPathNavigable>();
                }

                return null;
            }
        }

        /// <summary>
        /// Creates a <see cref="ChoiceItem" /> object
        /// </summary>
        /// <param name="index">
        /// The index.
        /// </param>
        /// <returns>
        /// the choice item object
        /// </returns>
        protected override OffspringItem CreateItem(int index)
        {
            return new ChoiceItem(this, index);
        }        
    }
}